package com.dal.rpc.core.consumer;

import com.dal.rpc.core.common.ProviderInfo;
import com.dal.rpc.core.common.RpcRequest;
import com.dal.rpc.core.common.RpcResponse;
import com.dal.rpc.core.registory.ServiceDiscovery;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Proxy;
import java.util.UUID;


/**
 * RPC 代理，用于创建 RPC 服务代理
 * 使用Netty客户端发送rpc请求，并获取反馈信息，拿到相关的服务调用类的相关方法调用结果
 * @author jian
 */
@Component
public class RpcProxy {

    private static final Logger logger = LoggerFactory.getLogger(RpcProxy.class);

    @Autowired
    private ServiceDiscovery serviceDiscovery;

    /**
     * 创建类方法
     * @param interfaceClass
     * @param <T>
     * @return
     */
    @SuppressWarnings("unchecked")
    public <T> T create(final Class<?> interfaceClass) {
        return create(interfaceClass, "");
    }

    /**
     * 创建类方法，带有服务版本参数
     * @param interfaceClass
     * @param providerName
     * @param <T>
     * @return
     */
    @SuppressWarnings("unchecked")
    public <T> T create(Class<?> interfaceClass, String providerName) {
        return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class<?>[]{interfaceClass},
                (proxy, method, args) -> {
                    // 通过netty向Rpc服务发送请求。
                    // 构建一个请求。
                    RpcRequest request = RpcRequest.builder()
                            .requestId(UUID.randomUUID().toString())
                            .interfaceName(method.getDeclaringClass().getName())
                            .methodName(method.getName())
                            .paramTypes(method.getParameterTypes())
                            .params(args)
                            .build();
                    System.out.println("================调用名称================"+interfaceClass.getName());
                    System.out.println("================调用名称================"+providerName);
                    // 获取一个服务提供者。
                    ProviderInfo providerInfo = serviceDiscovery.discover(providerName);
                    // 解析服务提供者的地址信息，数组第一个元素为ip地址，第二个元素为端口号。
                    String[] addrInfo = providerInfo.getAddr().split(":");
                    String host = addrInfo[0];
                    int port = Integer.parseInt(addrInfo[1]);
                    RpcClient rpcClient = new RpcClient(host, port);
                    long time = System.currentTimeMillis();
                    // 发送调用消息。
                    RpcResponse response = rpcClient.send(request);////获取rpc请求的反馈对象
                    System.out.println("调用时间为:" + String.valueOf(System.currentTimeMillis() - time)+"ms");
                    logger.debug("time: {}ms", System.currentTimeMillis() - time);//日志打印请求处理时间
                    if (response.isError()) {
                        throw response.getError();
                    } else {
                        return response.getResult();
                    }
                });
    }

    public void setServiceDiscovery(ServiceDiscovery serviceDiscovery) {
        this.serviceDiscovery = serviceDiscovery;
    }
}
